package com.fingard.dsp.bank.directbank.fngrd01;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fingard.constant.Format;
import com.fingard.crypto.DigestHelper;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.IStatement;
import com.fingard.dsp.bank.directbank.fngrd01.util.ExcelUtil;
import com.fingard.dsp.bank.directbank.fngrd01.util.HttpUtils;
import com.fingard.dsp.bank.reqrespobj.statement.ReqQryStatement;
import com.fingard.dsp.bank.reqrespobj.statement.RetAtsStatement;
import com.fingard.dsp.bank.reqrespobj.statement.TransState;
import com.fingard.dsp.bank.reqrespobj.statement.detail.RetAtsStatementDetail;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;

public class FnGrd01Statement extends FnGrd01Base implements IStatement {
    @Override
    public RetAtsStatement d_Qry_Statement(ReqQryStatement p_reqQrySttm) throws Exception {
        String commandCode = p_reqQrySttm.reqHeader.commandCode;
        if ("DownloadQRPayForCashier".equals(commandCode)) {
            return d_Qry_StatementForCashier(p_reqQrySttm);
        } else {
            return d_Qry_StatementForWebApi(p_reqQrySttm);
        }

    }

    public RetAtsStatement d_Qry_StatementForCashier(ReqQryStatement p_reqQrySttm) throws Exception {
        RetAtsStatement retAts = new RetAtsStatement(p_reqQrySttm);
        retAts.writeStart();

        String[] qrPayRespHeader = getQRPayStatementForCashier(p_reqQrySttm, retAts);

        String qrPayTotalNum = retAts.totalNum;
        if ("".equals(qrPayTotalNum)) {
            qrPayTotalNum = "0";
        }

        if ("-1".equals(qrPayRespHeader[0])) {
            retAts.writeRespCode("-1");
            retAts.writeRespInfo("扫码付对账单获取失败,原因:" + qrPayRespHeader[1]);
        } else {
            if (retAts.getWrittenRdCount() == 0) {
                retAts.writeRespCode("0");

                String respInfo = "";
                if (StringHelper.isNullOrEmpty(respInfo)) {
                    respInfo = qrPayRespHeader[1];
                }
                if (StringHelper.isNullOrEmpty(respInfo)) {
                    respInfo = "交易为空";
                }
                retAts.writeRespInfo(respInfo);
            }

            retAts.isWritedTotalNum(String.valueOf(Integer.parseInt(qrPayTotalNum)));
        }

        retAts.writeEnd();
        return retAts;
    }

    public RetAtsStatement d_Qry_StatementForWebApi(ReqQryStatement p_reqQrySttm) throws Exception {
        RetAtsStatement retAts = new RetAtsStatement(p_reqQrySttm);
        retAts.writeStart();
        boolean tmpswith = false;
        String statementType = "";
        ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "swith");
        if (actItem != null && actItem.billType.length() > 0) {
            tmpswith = true;
            statementType = actItem.billType;
        }

        String[] realTimeRespHeader = new String[]{"", ""};
        String realTimeTotalNum = "0";
        String[] qrPayCashRespHeader = new String[]{"", ""};
        String qrPayCashTotalNum = "0";
        String[] qrPayRespHeader = new String[]{"", ""};
        String qrPayTotalNum = "0";

        String[] qrAppRespHeader = new String[]{"", ""};
        String qrAppTotalNum = "0";
        String[] qrSglRealRespHeader = new String[]{"", ""};
        String qrSglRealTotalNum = "0";
        if (StringHelper.hasAnyChar(p_reqQrySttm.batFlag)) {
            if ("BATCH".equals(p_reqQrySttm.batFlag)) {
                if (tmpswith && !statementType.toLowerCase().contains("realtime")) {
                    //WriteBankLogLn("获取方式不包括单笔实时");
                } else {
                    WriteBankLogLn("获取单笔实时对账单开始");
                    realTimeRespHeader = getRealTimeStatement(p_reqQrySttm, retAts);
                    realTimeTotalNum = retAts.totalNum;
                    if ("".equals(realTimeTotalNum)) {
                        realTimeTotalNum = "0";
                    }
                }
            } else if ("SINGLE".equals(p_reqQrySttm.batFlag)) {
                if (tmpswith && !statementType.toLowerCase().contains("sglreal")) {

                } else {
                    qrSglRealRespHeader = getSglRealStatement(p_reqQrySttm, retAts);
                    qrSglRealTotalNum = retAts.totalNum;
                    if ("".equals(qrSglRealTotalNum)) {
                        qrSglRealTotalNum = "0";
                    }
                }
            } else {
                retAts.writeRespCode("-1");
                retAts.writeRespInfo("'BatchFlag'节点的值不为SINGLE或者BATCH,请检查'BatchFlag'节点的值！");
                retAts.writeEnd();
                return retAts;
            }
        } else {
            if (tmpswith && !statementType.toLowerCase().contains("realtime")) {
                //WriteBankLogLn("获取方式不包括单笔实时");
            } else {
                WriteBankLogLn("获取单笔实时对账单开始");
                realTimeRespHeader = getRealTimeStatement(p_reqQrySttm, retAts);
                realTimeTotalNum = retAts.totalNum;
                if ("".equals(realTimeTotalNum)) {
                    realTimeTotalNum = "0";
                }
            }

            if (tmpswith && !statementType.toLowerCase().contains("forcashier")) {

            } else if (!"F".equalsIgnoreCase(p_reqQrySttm.statementType)) {
                WriteBankLogLn("获取线上收单对账单开始");
                qrPayCashRespHeader = getQRPayStatementForCashier(p_reqQrySttm, retAts);
                qrPayCashTotalNum = retAts.totalNum;
                if ("".equals(qrPayCashTotalNum)) {
                    qrPayCashTotalNum = "0";
                }
            }

            if (tmpswith && !statementType.toLowerCase().contains("scan")) {
                //WriteBankLogLn("不获取扫码付对账单获取");
            } else if (!"F".equalsIgnoreCase(p_reqQrySttm.statementType)) {
                WriteBankLogLn("获取扫码付对账单开始");
                qrPayRespHeader = getQRPayStatement(p_reqQrySttm, retAts);
                qrPayTotalNum = retAts.totalNum;
                if ("".equals(qrPayTotalNum)) {
                    qrPayTotalNum = "0";
                }
            }
            if (tmpswith && !statementType.toLowerCase().contains("forapp")) {

            } else {
                qrAppRespHeader = getQRPayStatementForApp(p_reqQrySttm, retAts);
                qrAppTotalNum = retAts.totalNum;
                if ("".equals(qrAppTotalNum)) {
                    qrAppTotalNum = "0";
                }
            }

            if (tmpswith && !statementType.toLowerCase().contains("sglreal")) {

            } else {
                qrSglRealRespHeader = getSglRealStatement(p_reqQrySttm, retAts);
                qrSglRealTotalNum = retAts.totalNum;
                if ("".equals(qrSglRealTotalNum)) {
                    qrSglRealTotalNum = "0";
                }
            }
        }
        if ("-1".equals(realTimeRespHeader[0]) && "-1".equals(qrPayRespHeader[0]) && "-1".equals(qrAppRespHeader[0]) && "-1".equalsIgnoreCase(qrPayCashRespHeader[0]) && "-1".equalsIgnoreCase(qrSglRealRespHeader[0])) {
            retAts.writeRespCode("-1");
            retAts.writeRespInfo("单笔实时对账单获取失败,原因:" + realTimeRespHeader[1]
                    + ";扫码付对账单获取失败,原因:" + qrPayRespHeader[1]
                    + ";线上收单对账单获取失败,原因:" + qrPayCashRespHeader[1]
                    + ";单笔实时业务交易清单对账单获取失败,原因:" + qrSglRealRespHeader[1]);
        } else {
            if (retAts.getWrittenRdCount() == 0) {
                retAts.writeRespCode("0");
                String respInfo = realTimeRespHeader[1];
                if (StringHelper.isNullOrEmpty(respInfo)) {
                    respInfo = qrPayRespHeader[1];
                }
                if (StringHelper.isNullOrEmpty(respInfo)) {
                    respInfo = qrPayCashRespHeader[1];
                }
                if (StringHelper.isNullOrEmpty(respInfo)) {
                    respInfo = qrSglRealRespHeader[1];
                }
                if (StringHelper.isNullOrEmpty(respInfo)) {
                    respInfo = "交易为空";
                }
                retAts.writeRespInfo(respInfo);
            }

            retAts.isWritedTotalNum(String.valueOf(Integer.parseInt(realTimeTotalNum) + Integer.parseInt(qrPayTotalNum) + Integer.parseInt(qrAppTotalNum) + Integer.parseInt(qrPayCashTotalNum) + Integer.parseInt(qrSglRealTotalNum)));
        }
        retAts.writeEnd();
        return retAts;

    }

    /**
     * 单笔实时代收付对账单
     *
     * @param p_reqQrySttm
     * @param retAts
     * @return
     * @throws Exception
     */
    private String[] getRealTimeStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] tmpRespHeader = new String[]{"", ""};

        String tmpRespCode = "";
        String tmpRespInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "");
            if (actItem != null) {
                FnGrd01Header bankHeader = new FnGrd01Header();

                bankHeader.CommandCode = "21171";
                if (p_reqQrySttm.reqHeader.bankCode.length() == 8) {
                    bankHeader.CorpBankCode = p_reqQrySttm.reqHeader.bankCode.substring(5);
                } else {
                    bankHeader.CorpBankCode = getBankConfig().getMapValueByKey("corBankCodeMapping", p_reqQrySttm.actNum);
                }
                if (StringHelper.isNullOrEmpty(bankHeader.CorpBankCode)) {
                    WriteBankLogLn2("CorpBankCode为空，请配置corBankCodeMapping映射");
                }
                bankHeader.TransSeqID = getQryTransID();
                bankHeader.SourceChannel = "";

                XmlTextWriter xmlWriter = new XmlTextWriter();
                writeRealTimeCommonHeader(xmlWriter, bankHeader);

                xmlWriter.writeStartElement("ReconciliationReq");
                xmlWriter.writeElementString("ReconcileDate", Format.Date8Format.format(p_reqQrySttm.getBusDate()));
                xmlWriter.writeElementString("BusinessType", "");/* 空表示全部 */
                xmlWriter.writeElementString("EnterpriseAccNum", "");
                xmlWriter.writeEndElement();
                xmlWriter.writeEndDocument();

                String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String tmpRetCode = tmpBkReader.getFirstText("/Root/Head/RespCode");
                        String tmpRetMsg = tmpBkReader.getFirstText("/Root/Head/RespInfo");

                        int tmpIntRespCode = -1;
                        if (StringHelper.hasAnyChar(tmpRetCode)) {
                            tmpIntRespCode = Integer.parseInt(tmpRetCode);

                            if (tmpIntRespCode >= 0) {
                                while (tmpBkReader.read("/Root/ReconciliationResp/DetailRecord")) {
                                    String transState = tmpBkReader.readedXElement.getSingleText("State");
                                    if ("2".equals(transState)) { /* 交易状态：2-成功, 3-失败 */
                                        RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();
                                        tmpRetDetail.askNumber = tmpBkReader.readedXElement.getSingleText("FlowNo");
                                        // 返回TransTime节点长度是8~20位变长，无法读到准确时间
                                        tmpRetDetail.busTime = Format.DateTime14Format.format(Format.Date8Format.parse(p_reqQrySttm.busDate));
                                        // 返回Amount节点长度是小数点后0~2位变长，无法准确得到正确格式金额(单位为元)
                                        double amount = Double.parseDouble(tmpBkReader.readedXElement.getSingleText("Amount"));
                                        tmpRetDetail.amount = Format.DecimalAmtFormat.format(amount);
                                        tmpRetDetail.oppAct = tmpBkReader.readedXElement.getSingleText("AccNum");
                                        tmpRetDetail.oppActName = tmpBkReader.readedXElement.getSingleText("AccName");
                                        tmpRetDetail.summary = tmpBkReader.readedXElement.getSingleText("Purpose");
                                        tmpRetDetail.memo = tmpBkReader.readedXElement.getSingleText("Memo");
                                        tmpRetDetail.transState = TransState.Success;
                                        String cdFlag = tmpBkReader.readedXElement.getSingleText("MoneyWay");
                                        if ("S".equals(p_reqQrySttm.statementType) && "S".equals(cdFlag)) {
                                            totalNum++;
                                            tmpRetDetail.cdFlag = "22";
                                            retAts.writeRetDetail(tmpRetDetail);
                                        } else if ("F".equals(p_reqQrySttm.statementType) && "F".equals(cdFlag)) {
                                            totalNum++;
                                            tmpRetDetail.cdFlag = "27";
                                            retAts.writeRetDetail(tmpRetDetail);
                                        } else if ("CDE".equals(p_reqQrySttm.statementType) || "".equals(p_reqQrySttm.statementType)) {
                                            totalNum++;
                                            if ("S".equals(cdFlag)) {
                                                tmpRetDetail.cdFlag = "22";
                                            } else {
                                                tmpRetDetail.cdFlag = "27";
                                            }
                                            retAts.writeRetDetail(tmpRetDetail);
                                        }
                                    }
                                }
                            } else {
                                tmpRespCode = "-1";

                                if (StringHelper.isNullOrEmpty(tmpRetMsg)) {
                                    tmpRespInfo = "前置返回查询失败RespCode：" + tmpRetCode;
                                } else {
                                    tmpRespInfo = tmpRetMsg;
                                }
                            }
                        }
                    } else {
                        tmpRespCode = "-1";
                        tmpRespInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRespCode = "-1";
                    tmpRespInfo = tmpStrRet[1];
                }
            } else {
                tmpRespCode = "-1";
                tmpRespInfo = "未找到账号:[" + p_reqQrySttm.actNum + "]商户信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();

            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();

            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        tmpRespHeader[0] = tmpRespCode;
        tmpRespHeader[1] = tmpRespInfo;

        return tmpRespHeader;
    }

    /**
     * 3.3.21	单笔实时业务交易清单查询
     *
     * @param p_reqQrySttm
     * @param retAts
     * @return
     * @throws Exception
     */
    private String[] getSglRealStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] tmpRespHeader = new String[]{"", ""};

        String tmpRespCode = "";
        String tmpRespInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "sglReal");
            if (actItem != null) {
                FnGrd01Header bankHeader = new FnGrd01Header();

                bankHeader.CommandCode = "201J6";
                if (p_reqQrySttm.reqHeader.bankCode.length() == 8) {
                    bankHeader.CorpBankCode = p_reqQrySttm.reqHeader.bankCode.substring(5);
                } else {
                    bankHeader.CorpBankCode = getBankConfig().getMapValueByKey("corBankCodeMapping", p_reqQrySttm.actNum);
                }
                if (StringHelper.isNullOrEmpty(bankHeader.CorpBankCode)) {
                    WriteBankLogLn2("CorpBankCode为空，请配置corBankCodeMapping映射");
                }
                bankHeader.TransSeqID = getQryTransID();
                bankHeader.SourceChannel = "";

                XmlTextWriter xmlWriter = new XmlTextWriter();
                writeRealTimeCommonHeader(xmlWriter, bankHeader);

                xmlWriter.writeStartElement("TransRecordReq");
                xmlWriter.writeElementString("ReconcileDate", Format.Date8Format.format(p_reqQrySttm.getBusDate()));
                xmlWriter.writeElementString("BusinessType", "");/* 空表示全部 */
                xmlWriter.writeElementString("EnterpriseAccNum", "");
                xmlWriter.writeEndElement();
                xmlWriter.writeEndDocument();

                String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String tmpRetCode = tmpBkReader.getFirstText("/Root/Head/RespCode");
                        String tmpRetMsg = tmpBkReader.getFirstText("/Root/Head/RespInfo");

                        int tmpIntRespCode = -1;
                        if (StringHelper.hasAnyChar(tmpRetCode)) {
                            tmpIntRespCode = Integer.parseInt(tmpRetCode);

                            if (tmpIntRespCode >= 0) {
                                while (tmpBkReader.read("/Root/TransRecordResp/DetailRecord")) {
                                    String transState = tmpBkReader.readedXElement.getSingleText("State");
                                    if ("2".equals(transState)) { /* 交易状态：2-成功, 3-失败 */
                                        RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();
                                        tmpRetDetail.askNumber = tmpBkReader.readedXElement.getSingleText("FlowNo");
                                        // 返回TransTime节点长度是8~20位变长，无法读到准确时间
                                        tmpRetDetail.busTime = Format.DateTime14Format.format(Format.Date8Format.parse(p_reqQrySttm.busDate));
                                        // 返回Amount节点长度是小数点后0~2位变长，无法准确得到正确格式金额(单位为元)
                                        double amount = Double.parseDouble(tmpBkReader.readedXElement.getSingleText("Amount"));
                                        tmpRetDetail.amount = Format.DecimalAmtFormat.format(amount);
                                        tmpRetDetail.oppAct = tmpBkReader.readedXElement.getSingleText("AccNum");
                                        tmpRetDetail.oppActName = tmpBkReader.readedXElement.getSingleText("AccName");
                                        tmpRetDetail.summary = tmpBkReader.readedXElement.getSingleText("Purpose");
                                        tmpRetDetail.memo = tmpBkReader.readedXElement.getSingleText("Memo");
                                        tmpRetDetail.transState = TransState.Success;
                                        String cdFlag = tmpBkReader.readedXElement.getSingleText("MoneyWay");
                                        if ("S".equals(p_reqQrySttm.statementType) && "S".equals(cdFlag)) {
                                            totalNum++;
                                            tmpRetDetail.cdFlag = "22";
                                            retAts.writeRetDetail(tmpRetDetail);
                                        } else if ("F".equals(p_reqQrySttm.statementType) && "F".equals(cdFlag)) {
                                            totalNum++;
                                            tmpRetDetail.cdFlag = "27";
                                            retAts.writeRetDetail(tmpRetDetail);
                                        } else if ("CDE".equals(p_reqQrySttm.statementType) || "".equals(p_reqQrySttm.statementType)) {
                                            totalNum++;
                                            if ("S".equals(cdFlag)) {
                                                tmpRetDetail.cdFlag = "22";
                                            } else {
                                                tmpRetDetail.cdFlag = "27";
                                            }
                                            retAts.writeRetDetail(tmpRetDetail);
                                        }
                                    }
                                }
                            } else {
                                tmpRespCode = "-1";

                                if (StringHelper.isNullOrEmpty(tmpRetMsg)) {
                                    tmpRespInfo = "前置返回查询失败RespCode：" + tmpRetCode;
                                } else {
                                    tmpRespInfo = tmpRetMsg;
                                }
                            }
                        }
                    } else {
                        tmpRespCode = "-1";
                        tmpRespInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRespCode = "-1";
                    tmpRespInfo = tmpStrRet[1];
                }
            } else {
                tmpRespCode = "-1";
                tmpRespInfo = "未找到账号:[" + p_reqQrySttm.actNum + "]商户信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();

            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();

            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        tmpRespHeader[0] = tmpRespCode;
        tmpRespHeader[1] = tmpRespInfo;

        return tmpRespHeader;
    }

    /**
     * 扫码付对账单
     *
     * @param p_reqQrySttm
     * @param retAts
     * @return
     * @throws Exception
     */
    private String[] getQRPayStatement(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] tmpRespHeader = new String[]{"", ""};

        String tmpRespCode = "";
        String tmpRespInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "unifiedorder");
            if (actItem != null) {
                HashMap<String, String> mapParams = new HashMap<String, String>();

                mapParams.put("EnterpriseNum", actItem.inMerchantId); /* 保融分配的代表某个企业的编号 */
                mapParams.put("MchId", actItem.merchantId);
                mapParams.put("Billdate", p_reqQrySttm.busDate);
                /** 账单日期，格式：yyyyMMdd */
                mapParams.put("PaymentChannel", getBankConfig().getMapValueByKey("statementType", "paymentChannel"));
                /** 缴费渠道，微信：W210,支付宝：Z310，空表示全部渠道 */
                mapParams.put("NonceStr", get_nonce_str());

                // 签名
                String waitSignData = getSignStr(mapParams, actItem.saltKey);
                String signature = signFnGrd(actItem, waitSignData);

                mapParams.put("Signature", signature);

                // post请求数据
                String reqPostJson = getReqPostJson(mapParams);
                String reqSendData = getReqSendData(actItem.inMerchantId, reqPostJson);

                String[] tmpStrRet = sendToFnGrd(reqSendData, bankFront.getUrl("DownloadQRPay"));

                if (tmpStrRet[0].length() == 0) {
                    if (tmpStrRet[1].indexOf("Status") > 0) {
                        JSONObject respJSON = JSON.parseObject(tmpStrRet[1]);

                        String status = respJSON.getString("Status");
                        if ("-1".equals(status)) {
                            tmpRespCode = "-1";
                            tmpRespInfo = respJSON.getString("ReturnMsg");
                        }
                    } else if ("Not Found".equals(tmpStrRet[1])) {
                        tmpRespCode = "0";
                        tmpRespInfo = "本日无交易";
                    } else {
                        String respPostStr = getRespPostData(tmpStrRet[1]);
                        if (respPostStr.indexOf("Status") > 0) {
                            JSONObject respJSONObj = JSON.parseObject(respPostStr);
                            tmpRespCode = "-1";
                            tmpRespInfo = respJSONObj.getString("ReturnMsg");
                        } else {
                            StringBuilder tmpSbMsg = new StringBuilder();
                            XmlTextReader tmpBkReader = loadBankRespXmlReader(respPostStr, tmpSbMsg);
                            if (tmpBkReader != null) {
                                String statusType = getBankConfig().getMapValueByKey("statementType", "statusType");
                                while (tmpBkReader.read("/ReconciliationResp/DetailRecord")) {
                                    if ("success".equals(statusType)) {
                                        if ("2".equals(tmpBkReader.readedXElement.getSingleText("State"))) {
                                            totalNum++;
                                        }
                                    } else if ("all".equals(statusType)) {
                                        totalNum++;
                                    } else {
                                        tmpRespHeader[0] = "-1";
                                        tmpRespHeader[1] = "错误的对账单类型:[" + statusType + "],请检查相应配置文件。";

                                        return tmpRespHeader;
                                    }
                                }

                                XmlTextReader tmpBankReader = loadBankRespXmlReader(respPostStr, new StringBuilder());
                                if ("success".equals(statusType)) {
                                    while (tmpBankReader.read("/ReconciliationResp/DetailRecord")) {
                                        if ("2".equals(tmpBankReader.readedXElement.getSingleText("State"))) {
                                            RetAtsStatementDetail retDetail = new RetAtsStatementDetail();

                                            String busiTime = tmpBankReader.readedXElement.getSingleText("ResultDate");

                                            retDetail.askNumber = tmpBankReader.readedXElement.getSingleText("ExchangeNo");
                                            retDetail.busTime = Format.DateTime14Format.format(Format.Date10Format.parse(busiTime));
                                            retDetail.amount = tmpBankReader.readedXElement.getSingleText("Amount");
                                            String creditDebitFlag = tmpBkReader.readedXElement.getSingleText("MoneyWay");// 收付方向，S(收)/F(付)
                                            if (creditDebitFlag != null) {
                                                if (creditDebitFlag.equals("F")) // 借贷标识
                                                {
                                                    retDetail.cdFlag = "27";
                                                } else {
                                                    retDetail.cdFlag = "22";
                                                }
                                            }
                                            retDetail.oppAct = tmpBankReader.readedXElement.getSingleText("PayedAccNum");
                                            retDetail.oppActName = tmpBankReader.readedXElement.getSingleText("PayedAccName");
                                            retDetail.channelOrderNo = tmpBankReader.readedXElement.getSingleText("FGTradeNo");
                                            retDetail.bankOrderNo = tmpBankReader.readedXElement.getSingleText("BankOrderNo");
                                            retDetail.summary = tmpBankReader.readedXElement.getSingleText("Purpose");

                                            retDetail.transState = TransState.Success;

                                            retAts.writeRetDetail(retDetail);
                                        }
                                    }
                                } else {
                                    while (tmpBankReader.read("/ReconciliationResp/DetailRecord")) {
                                        RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();
                                        tmpRetDetail.askNumber = tmpBankReader.readedXElement.getSingleText("ExchangeNo");
                                        tmpRetDetail.busTime = Format.DateTime14Format.format(Format.Date10Format.parse(tmpBankReader.readedXElement.getSingleText("ResultDate")));
                                        tmpRetDetail.amount = tmpBankReader.readedXElement.getSingleText("Amount");
                                        String creditDebitFlag = tmpBankReader.readedXElement.getSingleText("MoneyWay");// 收付方向，S(收)/F(付)
                                        if (creditDebitFlag != null) {
                                            if (creditDebitFlag.equals("F")) {
                                                tmpRetDetail.cdFlag = "22";
                                            } else {
                                                tmpRetDetail.cdFlag = "22";
                                            }
                                        }
                                        String state = tmpBankReader.readedXElement.getSingleText("State");
                                        if ("2".equals(state)) {
                                            tmpRetDetail.transState = TransState.Success;
                                        } else {
                                            if ("4".equals(state)) {
                                                // 退款
                                                tmpRetDetail.askNumber = tmpBankReader.readedXElement.getSingleText("EnterpriseRefundNo");
                                                tmpRetDetail.cdFlag = "27";
                                                tmpRetDetail.transState = TransState.ToRefund;
                                            }
                                        }
                                        retAts.writeRetDetail(tmpRetDetail);
                                    }
                                }
                            } else {
                                tmpRespCode = "-1";
                                tmpRespInfo = tmpSbMsg.toString();
                            }
                        }
                    }
                } else {
                    tmpRespCode = "-1";
                    tmpRespInfo = tmpStrRet[1];
                }
            } else {
                tmpRespCode = "0";
                tmpRespInfo = "未找到账号:[" + p_reqQrySttm.actNum + "]商户信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);
        tmpRespHeader[0] = tmpRespCode;
        tmpRespHeader[1] = tmpRespInfo;

        return tmpRespHeader;
    }

    private String[] getQRPayStatementForCashier(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] tmpRespHeader = new String[]{"", ""};

        String tmpRespCode = "";
        String tmpRespInfo = "";

        int totalNum = 0;
        int detailNum = 0;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "unifiedorder");
            if (actItem != null) {
//				Map<String, String> signMap = new HashMap<String, String>();

                SimpleDateFormat dateFormat8 = new SimpleDateFormat("yyyyMMdd");
                SimpleDateFormat dateFormat10 = new SimpleDateFormat("yyyy-MM-dd");
                // 获取签名字符串,对账日期_接入方式_缴费渠道_组织机构号_企业方账号
                StringBuilder signStr = new StringBuilder();
                signStr.append(dateFormat10.format(dateFormat8.parse(p_reqQrySttm.busDate))).append("_");
                signStr.append("").append("_");
                signStr.append("").append("_");
                signStr.append("").append("_");
                signStr.append("");
                // 签名
                String signature = signFnGrd(actItem, signStr.toString());

                SimpleDateFormat dateFormat18 = new SimpleDateFormat("yyyyMMddHHmmssSSSS");
                XmlTextWriter xmlWriter = new XmlTextWriter();
                xmlWriter.writeStartElement("Root");
                xmlWriter.writeStartElement("Head");
                xmlWriter.writeElementString("EnterpriseNum", actItem.inMerchantId);
                xmlWriter.writeElementString("CommandCode", "50001");
                xmlWriter.writeElementString("TransSeqID", dateFormat18.format(new Date()));
                xmlWriter.writeElementString("VerifyCode", signature);
                xmlWriter.writeEndElement();
                xmlWriter.writeStartElement("ReconciliationReq");

                xmlWriter.writeElementString("ReconcileDate", dateFormat10.format(dateFormat8.parse(p_reqQrySttm.busDate)));
                xmlWriter.writeElementString("ConnectingMode", "");
                xmlWriter.writeElementString("PaymentChannel", "");
                xmlWriter.writeElementString("ComCode", "");
//				xmlWriter.writeElementString("ComCode", p_reqQrySttm.actNum);
                xmlWriter.writeElementString("MchId", p_reqQrySttm.actNum);
                xmlWriter.writeElementString("EnterpriseAccNum", "");
                xmlWriter.writeEndDocument();
                String reqSendData = getReqSendData(actItem.inMerchantId, xmlWriter.toXmlString(), "GBK");

                // 服务地址
                String url = bankFront.getUrl("DownloadQRPayForCashier").trim();

                if (StringHelper.isNullOrEmpty(url)) {
                    tmpRespCode = "0";
                    tmpRespInfo = "融汇扫码付(收银台)对账单下载服务地址为空,请检查BankFront.xml相关配置!";
                }
                String tmpRetStr = sendUnifiedToBank(reqSendData, url);
                // 解密获得的返回参数
                String respData = this.getRespPostData(tmpRetStr, "GBK", "");
                // 解析返回的xml报文
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBankReader = loadBankRespXmlReader(respData, tmpSbMsg);

                // 验签字符串
                String verifyCode = "";
                StringBuilder tmpRespSignStr = new StringBuilder();

                if (tmpBankReader != null) {
                    totalNum = Integer.parseInt(tmpBankReader.getFirstText("/Root/ReconciliationResp/TotalNum"));
                    verifyCode = tmpBankReader.getFirstText("/Root/Head/VerifyCode");
                    String reconcileDate = tmpBankReader.getFirstText("/Root/ReconciliationResp/ReconcileDate");
                    String totalAmount = tmpBankReader.getFirstText("/Root/ReconciliationResp/TotalAmount");
//					signMap.put(stringToAscii("0"), reconcileDate + "_" + totalNum + "_" + totalAmount);
                    tmpRespSignStr.append(reconcileDate).append("_")
                            .append(totalNum).append("_")
                            .append(totalAmount).append(";");
                    String[] detailSignArrays = new String[totalNum];
                    while (tmpBankReader.read("/Root/ReconciliationResp/DetailRecord")) {
                        String State = tmpBankReader.readedXElement.getSingleText("State");
                        RetAtsStatementDetail retDetail = new RetAtsStatementDetail();

                        String busiTime = tmpBankReader.readedXElement.getSingleText("ResultDate");
                        retDetail.askNumber = tmpBankReader.readedXElement.getSingleText("ExchangeNo");
                        retDetail.busTime = Format.DateTime14Format.format(Format.Date10Format.parse(busiTime));
                        retDetail.amount = tmpBankReader.readedXElement.getSingleText("Amount");
                        retDetail.oppAct = tmpBankReader.readedXElement.getSingleText("PayedAccNum");
                        retDetail.oppActName = tmpBankReader.readedXElement.getSingleText("PayedAccName");
                        retDetail.channelOrderNo = tmpBankReader.readedXElement.getSingleText("FGTradeNo");
                        retDetail.bankOrderNo = tmpBankReader.readedXElement.getSingleText("BankOrderNo");
                        retDetail.summary = tmpBankReader.readedXElement.getSingleText("Purpose");
                        // 20180913:新增手续费字段，该字段并不是所有客户都会返回，通过在融汇那里配置来决定是否回传，同时，有可能在
                        // 标准接口文档中不存在该字段，原因是标准接口文档是面向所有客户。
                        retDetail.fee = tmpBankReader.readedXElement.getSingleText("Cost");

                        if ("2".equals(State)) {
                            retDetail.transState = TransState.Success;
                        } else if ("3".equals(State)) {
                            retDetail.transState = TransState.Fail;
                        } else if ("4".equals(State)) {
                            retDetail.transState = TransState.Paying;
                        } else if ("5".equals(State)) {
                            retDetail.transState = TransState.ToRefund;
                        } else if ("7".equals(State)) {
                            retDetail.transState = TransState.RefundTicket;
                        }
                        detailSignArrays[detailNum] = retDetail.askNumber + "_" + retDetail.amount + "_" + State;
//						signMap.put(stringToAscii(retDetail.askNumber + "_" + retDetail.amount + "_" + State), retDetail.askNumber + "_" + retDetail.amount + "_" + State);
                        String creditDebitFlag = tmpBankReader.readedXElement.getSingleText("MoneyWay");// 收付方向，S(收)/F(付)
                        if (creditDebitFlag != null) { //应融汇要求，正负通过S/F确定，22为收入，27为支出
                            if (retDetail.amount.indexOf("-") >= 0) {
                                retDetail.amount = retDetail.amount.substring(1); //兼容改之前的对账单
                            }
                            if (creditDebitFlag.equals("S")) // 收
                            {
                                retDetail.cdFlag = "22";
                            } else if (creditDebitFlag.equals("F")) { //付
                                retDetail.cdFlag = "27";
                            }
                        }

                        //对账接口返回新增组织机构号字段、商户实收金额、买家实付金额、商家优惠金额、平台优惠金额
                        retDetail.organizationId = tmpBankReader.readedXElement.getSingleText("OrganizationId");//组织机构号
                        retDetail.receiptAmount = tmpBankReader.readedXElement.getSingleText("ReceiptAmount");//商户实收金额
                        retDetail.buyerPayAmount = tmpBankReader.readedXElement.getSingleText("BuyerPayAmount");//买家实付金额
                        retDetail.mDiscountAmount = tmpBankReader.readedXElement.getSingleText("MDiscountAmount");//商家优惠金额
                        retDetail.discountAmount = tmpBankReader.readedXElement.getSingleText("DiscountAmount");//平台优惠金额


                        retAts.writeRetDetail(retDetail);
                        detailNum++;
                    }
                    if (detailNum != totalNum) {
                        tmpRespCode = "-1";
                        tmpRespInfo = "遍历的对账单明细条数与总数据条数不相符";
                    }
//					signMap = SortHelper.sortMapByName(signMap);
					/*for (String keys : signMap.keySet()) {
						tmpRespSignStr.append(signMap.get(keys)).append(";");
					}*/
                    //排序
                    Arrays.sort(detailSignArrays);
                    int length = detailSignArrays.length;
                    for (int i = 0; i < length; i++) {
                        tmpRespSignStr.append(detailSignArrays[i]).append(";");
                    }
                    // 执行验签
                    boolean verifySignResult = verifyFnGrd(tmpRespSignStr.toString(), verifyCode, actItem);
                    if (!verifySignResult) {
                        tmpRespCode = "-1";
                        tmpRespInfo = "返回对账单数据签名验签错误";
                    }
                } else {
                    tmpRespCode = "-1";
                    tmpRespInfo = tmpSbMsg.toString();
                }

            } else {
                tmpRespCode = "0";
                tmpRespInfo = "未找到账号:[" + p_reqQrySttm.actNum + "]商户信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();

            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();

            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        tmpRespHeader[0] = tmpRespCode;
        tmpRespHeader[1] = tmpRespInfo;

        return tmpRespHeader;
    }

    private String[] getQRPayStatementForApp(ReqQryStatement p_reqQrySttm, RetAtsStatement retAts) throws Exception {
        String[] tmpRespHeader = new String[]{"", ""};

        String tmpRespCode = "";
        String tmpRespInfo = "";

        retAts.totalNum = "0";
        int totalNum = 0;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQrySttm.actNum, "appOrder");
            if (actItem != null) {
                HashMap<String, Object> reqMap = new HashMap<String, Object>();

                reqMap.put("enterpriseNum", actItem.inMerchantId);
                reqMap.put("method", "downloadReconcileFile");
                reqMap.put("format", "JSON");
                reqMap.put("charset", getCharset());
                reqMap.put("signType", "MD5");
                reqMap.put("transSeqID", Format.DateTime17SSSFormat.format(new Date()));
                reqMap.put("version", "1.0");

                HashMap<String, String> bizContentMap = new HashMap<String, String>();

                bizContentMap.put("billdate", Format.Date8Format.format(p_reqQrySttm.getBusDate()));
                bizContentMap.put("payType", "");
                bizContentMap.put("organizationId", "");
                bizContentMap.put("acquireWay", "1");
                bizContentMap.put("merchantId", actItem.merchantId);
                reqMap.put("bizContent", bizContentMap);

                String signStr = oriSignStr(reqMap, actItem.saltKey);
                WriteBankLogLn2("签名原始数据:\r\n" + signStr);

                String signature = DigestHelper.cryptoMD5RetHexStr(signStr.getBytes(getCharset()));
                reqMap.put("sign", signature);
                String reqPostJson = getPostJson(reqMap);
                WriteBankLogStep2(reqPostJson);

                String tmpStrRet = HttpUtils.doPost(bankFront.getUrl("appOrderQry"), "", reqPostJson.getBytes(getCharset()), 50000, 50000, "", 0);
                WriteBankLogStep3(tmpStrRet);

                JSONObject tmpRespJson = JSON.parseObject(tmpStrRet);
                String code = tmpRespJson.getString("code");
                String bizCode = tmpRespJson.getString("bizCode");
                String bizMsg = tmpRespJson.getString("bizMsg");
                if ("0".equals(code) && "0".equals(bizCode)) {
                    String tmpRespFileURL = tmpRespJson.getString("file");
                    WriteBankLogLn2("待下载文件链接:" + tmpRespFileURL);
                    String decodeURL = URLDecoder.decode(tmpRespFileURL, "UTF-8");
                    String fileName = tmpRespFileURL.substring(decodeURL.lastIndexOf("/") + 1);
                    String localFilePath = createTempFileDirectory() + File.separator + fileName;
                    smsGet(tmpRespFileURL, localFilePath);
                    WriteBankLogLn2("文件下载后存储本地文件路径:" + localFilePath);

                    String excelContent = ExcelUtil.read(localFilePath);
                    WriteBankLogLn("明细对账文件内容:\r\n" + excelContent);

                    StringReader strReader = new StringReader(excelContent);
                    BufferedReader tmpReader = new BufferedReader(strReader);

                    while (true) {
                        String eachline = tmpReader.readLine();
                        if (eachline == null) {
                            break;
                        }
                        totalNum++;
                        String[] eachNodes = eachline.split(",");
                        RetAtsStatementDetail tmpRetDetail = new RetAtsStatementDetail();

                        if (StringHelper.hasAnyChar(eachNodes[1])) {
                            tmpRetDetail.askNumber = eachNodes[1];
                        }

                        if (StringHelper.hasAnyChar(eachNodes[12])) {
                            tmpRetDetail.amount = eachNodes[12];
                        }

                        if (StringHelper.hasAnyChar(eachNodes[4])) {
                            tmpRetDetail.busTime = Format.DateTime14Format.format(Format.DateTimeFormat.parse(eachNodes[4]));
                        }

                        if (StringHelper.hasAnyChar(eachNodes[10])) {
                            tmpRetDetail.oppAct = eachNodes[10];
                        }

                        if (StringHelper.hasAnyChar(eachNodes[9])) {
                            tmpRetDetail.oppActName = eachNodes[9];
                        }

                        if (StringHelper.hasAnyChar(eachNodes[2])) {
                            tmpRetDetail.bankOrderNo = eachNodes[2];
                        }

                        tmpRetDetail.cdFlag = "22";
                        tmpRetDetail.transState = TransState.Success;

                        retAts.writeRetDetail(tmpRetDetail);
                    }
                } else {
                    tmpRespHeader[0] = "-1";
                    tmpRespHeader[1] = bizMsg;
                }
            } else {
                tmpRespCode = "-1";
                tmpRespInfo = "未找到账号:[" + p_reqQrySttm.actNum + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.totalNum = String.valueOf(totalNum);

        tmpRespHeader[0] = tmpRespCode;
        tmpRespHeader[1] = tmpRespInfo;

        return tmpRespHeader;
    }

    private static String stringToAscii(String value) {
        StringBuffer sbu = new StringBuffer();
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            sbu.append((int) chars[i]);
        }
        return sbu.toString();
    }
}
